package com.kaisu.blog.application.blog.impl;

import com.kaisu.blog.application.blog.BlogApplication;
import com.kaisu.blog.application.blog.convert.BlogApplicationConvert;
import com.kaisu.blog.application.blog.dto.*;
import com.kaisu.blog.application.user.util.UserUtil;
import com.kaisu.blog.domain.blog.Blog;
import com.kaisu.blog.domain.blog.Comment;
import com.kaisu.blog.domain.blog.command.BlogCreateCommand;
import com.kaisu.blog.domain.blog.repostiroy.BlogRepository;
import com.kaisu.blog.domain.file.repository.FileRepository;
import com.kaisu.blog.domain.user.User;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.stereotype.Service;

import java.util.Collection;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @author kaisu
 */
@Service
@RequiredArgsConstructor
public class BlogApplicationImpl implements BlogApplication {
    private final BlogApplicationConvert applicationConvert;
    private final BlogRepository blogRepository;
    private final FileRepository fileRepository;

    @Override
    public void create(BlogCreateDTO dto) {
        Blog blog = Blog.create(new BlogCreateCommand(dto.title(), dto.content()), UserUtil.currentUser());
        blog.setCover(fileRepository.findById("1"));
        blogRepository.save(blog);
    }

    @Override
    public void updateTitle(String id, String title) {
        Blog blog = blogRepository.findById(id);
        User user = UserUtil.currentUser();
        blog.updateTitle(title, user);
        blogRepository.save(blog);
    }

    @Override
    public void editContent(String id, String content) {
        Blog blog = blogRepository.findById(id);
        User user = UserUtil.currentUser();
        blog.editConent(content, user);
        blogRepository.save(blog);
    }

    @Override
    public void deleteByIds(Collection<String> ids) {
        User user = UserUtil.currentUser();
        for (String id : ids) {
            Blog blog = blogRepository.findById(id);
            blog.checkAuth(user);
        }
        blogRepository.removeByIds(ids);
    }

    @Override
    public void publish(String id) {
        Blog blog = blogRepository.findById(id);
        User user = UserUtil.currentUser();
        blog.published(user);
        blogRepository.save(blog);
    }

    @Override
    public BlogDTO findById(String id) {
        Blog blog = blogRepository.findById(id);
        return applicationConvert.toDTO(blog);
    }

    @Override
    public void like(String id) {
        Blog blog = blogRepository.findById(id);
        blog.like(UserUtil.currentUser());
        blogRepository.save(blog);
    }

    @Override
    public void unlike(String blogId) {
        Blog blog = blogRepository.findById(blogId);
        blog.unLike(UserUtil.currentUser());
        blogRepository.save(blog);
    }

    @Override
    public void addComment(String blogId, String content) {
        Blog blog = blogRepository.findById(blogId);
        blog.appendComment(Comment.create(content, UserUtil.currentUser()));
        blogRepository.save(blog);
    }

    @Override
    public Page<BlogPageDTO> pageByUserId(BlogPageUserRequestDTO requestDTO) {
        return blogRepository.pageByUserId(requestDTO.userId(), requestDTO.page()).map(applicationConvert::toPageDTO);
    }

    @Override
    public Page<CommentPageDTO> commentPage(CommentPageRequestDTO requestDTO) {
        return blogRepository.commentPage(requestDTO.blogId(), requestDTO.page()).map(applicationConvert::toPageDTO);
    }

    @Override
    public Page<BlogPageDTO> blogPageBySearch(BlogPageSearchRequestDTO requestDTO) {
        return blogRepository.blogPageBySearch(requestDTO.key(), requestDTO.page()).map(applicationConvert::toPageDTO);
    }

    @Override
    public Page<BlogPageDTO> blogRecommend(PageRequest request) {
        return blogRepository.page(null, request).map(applicationConvert::toPageDTO);
    }

    @Override
    public Page<BlogPageDTO> myBlogPage(PageRequest request) {
        return blogRepository.myBlogPage(UserUtil.currentUser().getId(), request).map(applicationConvert::toPageDTO);
    }

    @Override
    public Page<BlogPageDTO> blogFollowings(PageRequest request) {
        User user = UserUtil.currentUser();
        Set<String> followingUserIds = user.getFollowings().stream().map(follow -> follow.getFollowing().getId()).collect(Collectors.toSet());
        return blogRepository.pageInUserIds(followingUserIds, request).map(applicationConvert::toPageDTO);
    }
}
